package com.hunttown.mes.manage.controller._erp;

import com.hunttown.mes.common.OperateCode;
import com.hunttown.mes.manage.controller.common.AdminBaseClass;
import com.hunttown.mes.manage.controller.common.ModelService;
import com.hunttown.mes.rpc.domain.AnalysisManageDTO;
import com.hunttown.mes.rpc.domain.TransportPurchaseDTO;
import com.hunttown.mes.rpc.domain.TransportPurchaseDetailDTO;
import com.hunttown.mes.rpc.domain.TransportPurchaseOutDTO;
import com.hunttown.mes.rpc.domain.enums.purchase.PurchaseDetailOutEnum;
import com.hunttown.mes.rpc.domain.query.TransportPurchaseDetailDTOQuery;
import com.hunttown.mes.rpc.domain.query.TransportPurchaseOutDTOQuery;
import com.hunttown.common.domain.Page;
import com.hunttown.mes.common.utils.DateConvertUtils;
import com.hunttown.mes.common.utils.GeneralUtils;
import com.hunttown.mes.common.utils.JSONUtils;
import com.hunttown.mes.common.utils.StringUtils;
import com.hunttown.mes.manage.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

import static com.hunttown.mes.common.utils.PageUtils.PagePackage;

/**
 * created by wangjunfu on 2022-03-05 09:16:15
 */
@Controller
@RequestMapping(value = "/erp/purchase-out")
public class PurchaseOutController {

    private final static Logger logger = LoggerFactory.getLogger(PurchaseOutController.class);

    private final AnalysisManageManageService manageService;
    private final ModelService modelService;
    private final TransportPurchaseManageService purchaseService;
    private final TransportPurchaseDetailManageService purchaseDetailService;
    private final TransportPurchaseOutManageService purchaseOutService;
    private final TransactionService transactionService;
    private final WorkflowApplyLineManageService applyLineService;
    private final WorkflowApplyManageService applyManageService;

    @Autowired
    public PurchaseOutController(AnalysisManageManageService manageService, ModelService modelService, TransportPurchaseManageService purchaseService, TransportPurchaseDetailManageService purchaseDetailService, TransportPurchaseOutManageService purchaseOutService, TransactionService transactionService, WorkflowApplyLineManageService applyLineService, WorkflowApplyManageService applyManageService) {
        this.manageService = manageService;
        this.modelService = modelService;
        this.purchaseService = purchaseService;
        this.purchaseDetailService = purchaseDetailService;
        this.purchaseOutService = purchaseOutService;
        this.transactionService = transactionService;
        this.applyLineService = applyLineService;
        this.applyManageService = applyManageService;
    }

    //region 数据列表

    /**
     * 首页
     *
     * @param model    model模型
     * @param dtoQuery 查询条件
     * @return model
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(HttpServletRequest request, Model model, TransportPurchaseOutDTOQuery dtoQuery) {

        //region 显示标题
        String showTitle = "未知";
        if (dtoQuery.getPurchaseType() == 1) {
            showTitle = "配件";
        }
        if (dtoQuery.getPurchaseType() == 2) { //采购
            showTitle = "物料";
        }
        model.addAttribute("showTitle", showTitle);
        //endregion

        String pin = AdminBaseClass.getPin(request);
        AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);

        // 领料日期（初始化 30天）
        if (StringUtils.isBlank(dtoQuery.getDaterange())) {
            dtoQuery.setDaterange(String.format("%s ~ %s", DateConvertUtils.getPastDate(30), DateConvertUtils.getPastDate(0)));
        }

        //dtoQuery.setStopFlag(0);    //是否显示撤回订单
        dtoQuery.setReceiver(modelService.completionUserId(dtoQuery.getReceiver(), dtoQuery.getReceiverCn(), -9999));
        dtoQuery.setTableId(0);
        dtoQuery.setOrderBy("order by id desc");
        Page<TransportPurchaseOutDTO> dataPage = purchaseOutService.getForPage(dtoQuery);

        for (TransportPurchaseOutDTO item : dataPage.getItems()) {
            item.setReceiverCn(modelService.getUserTrueName(item.getReceiver()));
            item.setOperatorCn(modelService.getManageName(item.getOperator()));
            item.setOutTypeName(PurchaseDetailOutEnum.getEnumByKey(item.getOutType()));

            //region 是否可以操作
            item.setCanExec(0);

            //只判断审核中，采购中和已入库不能改动
            if (item.getStatus() == 0) {
                //必须是[自己的]并且未进入[审批阶段]
                int nodesign = applyLineService.getCurrLineNodeSignIdByApplyId(item.getApplyId());
                if (item.getAdminId().equals(curr_obj.getId()) && nodesign == 1) {
                    item.setCanExec(1);
                }
            }
            //endregion
        }

        model.addAttribute("page", dataPage);
        model.addAttribute("PagePackage", PagePackage(dataPage.getPn(), dataPage.getStart(), dataPage.getPageSize(), dataPage.getTotalPages(), dataPage.getTotalItems()));
        model.addAttribute("dtoQuery", dtoQuery);

        //领料日期
        if (StringUtils.isNotBlank(dtoQuery.getDaterange())) {
            String[] date = dtoQuery.getDaterange().split("~");
            if (date.length == 2) {
                model.addAttribute("startDate", date[0].trim());
                model.addAttribute("endDate", date[1].trim());
            }
        }

        return "/erp/purchase-out/index";
    }
    //endregion

    //region 编辑&保存

    /**
     * 编辑
     *
     * @param model        model模型
     * @param id           主键id
     * @param purchaseType 采购类型：1汽车配件 2日常采购
     * @return model
     */
    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String edit(HttpServletRequest request, Model model, Integer id, Integer purchaseType) {
        id = (id == null ? 0 : id);

        TransportPurchaseOutDTO obj;

        if (id > 0) {
            obj = purchaseOutService.getById(id);
            obj.setReceiverCn(modelService.getUserTrueName(obj.getReceiver()));

            //region 获取出库明细
            TransportPurchaseDetailDTOQuery detailQuery = new TransportPurchaseDetailDTOQuery();
            detailQuery.setTableId(205);
            detailQuery.setPurId(id);
            detailQuery.setStopFlag(0);
            detailQuery.setPageSize(100);
            Page<TransportPurchaseDetailDTO> detailPage = purchaseDetailService.getForPage(detailQuery);
            for (TransportPurchaseDetailDTO item : detailPage.getItems()) {
                TransportPurchaseDTO dto = purchaseService.getFromCacheId(item.getPartId());
                if (dto != null) {
                    item.setPartName(dto.getPartName());
                    item.setPartNo(dto.getPartNo());
                    item.setSpecialName(dto.getSpecialName());
                }
            }
            model.addAttribute("partsDetailList", detailPage.getItems());
            //endregion

        } else {
            obj = new TransportPurchaseOutDTO();
            obj.setId(0);
            obj.setOutNo(GeneralUtils.GenTimeSeries(4, null, null));
            obj.setPurchaseType(purchaseType);
            obj.setCarId(0);
            obj.setDriverId(0);
            obj.setApplyId(0);
            obj.setRelationId(0);
            obj.setReceiveDate(new Date());
            obj.setOperateDate(new Date());

            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
            obj.setOperator(curr_obj.getId());
            obj.setOutName(String.format("%s的（请简写物料名称）出库单", curr_obj.getNickName()));
        }
        model.addAttribute("Obj", obj);

        //经办人
        modelService.getManagerPage(model);

        //出库方式
        model.addAttribute("purchaseOutList", PurchaseDetailOutEnum.getEnumList("1,2,3,4"));

        //region 显示标题
        String showTitle = "未知";
        if (purchaseType == 1) {
            showTitle = "配件";
        }
        if (purchaseType == 2) {
            showTitle = "物料";
        }
        model.addAttribute("showTitle", showTitle);
        //endregion

        return "/erp/purchase-out/edit";
    }

    /**
     * 保存 ajax异步
     *
     * @param request sevelet请求
     * @param objDTO  实体类
     * @return json
     */
    @RequestMapping(value = "/saveEdit", method = RequestMethod.POST)
    @ResponseBody
    public String saveEditNotify(HttpServletRequest request, TransportPurchaseOutDTO objDTO) {

        // 结果返回 结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        int outid = 0; //新生成的出库单ID
        int out_apply = 0; //新生成的审批ID

        try {
            if (objDTO.getReceiver() == 0) {
                map = OperateCode.CompositionResult(map, -10, "请选择领料人！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            if (objDTO.getOperator() == 0) {
                map = OperateCode.CompositionResult(map, -10, "请选择经办人！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            //日期
            objDTO.setReceiveDate(DateConvertUtils.strToDate(objDTO.getReceiveDateSr()));
            objDTO.setOperateDate(DateConvertUtils.strToDate(objDTO.getOperateDateSr()));

            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);

            if (objDTO.getId() == null || objDTO.getId() <= 0) {
                //新增
                //设置初始值
                objDTO.setAdminId(curr_obj.getId());
                objDTO.setCreateTime(new Date());
                objDTO.setStopFlag(0);
                objDTO.setDeleteFlag(0);

                //其它初始值
                objDTO.setParentId(0);
                objDTO.setTableId(0);
                objDTO.setRecordId(0);
                objDTO.setReviewer(0);
                objDTO.setReviewStatus(0);
                objDTO.setProId(0);
                objDTO.setStatus(0);

                objDTO = purchaseOutService.insert(objDTO);

                if (objDTO == null || objDTO.getId() <= 0) {
                    //操作失败
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }

                outid = objDTO.getId();

                //region 创建审批单
                Map<String, String> param = new HashMap<>();

                String businessNameEn = ""; //流程业务代码
                int firstExecutor = modelService.getUserIdByAdminId(objDTO.getOperator()); //经办人
                int secondExecutor = objDTO.getReceiver();   //领料人

                if (objDTO.getPurchaseType() == 1) {
                    //region [1].配件采购

                    //[1-1].正常出库
                    if (objDTO.getOutType() == 1) {
                        businessNameEn = "parts_outbound";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "无单出库"));

                        secondExecutor = modelService.getUserIdByDriverId(objDTO.getDriverId());
                    }

                    //[1-2].借用
                    if (objDTO.getOutType() == 2) {
                        businessNameEn = "parts_borrow";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "借用"));
                    }

                    //[1-3].退货
                    if (objDTO.getOutType() == 3) {
                        businessNameEn = "parts_return";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "退货"));
                    }

                    //[1-4].报废
                    if (objDTO.getOutType() == 4) {
                        businessNameEn = "parts_damage";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "报废"));
                    }
                    //endregion

                } else {
                    //region [2].物料采购

                    //[2-1].正常出库
                    if (objDTO.getOutType() == 1) {
                        businessNameEn = "goods_receiving";
                        param.put("applyTitle", objDTO.getOutName());
                    }

                    //[2-2].借用
                    if (objDTO.getOutType() == 2) {
                        businessNameEn = "goods_borrow";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "借用"));
                    }

                    //[2-3].退货
                    if (objDTO.getOutType() == 3) {
                        businessNameEn = "goods_return";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "退货"));
                    }

                    //[2-4].报废
                    if (objDTO.getOutType() == 4) {
                        businessNameEn = "goods_damage";
                        param.put("applyTitle", objDTO.getOutName().replace("出库", "报废"));
                    }
                    //endregion
                }

                //[改版后]审批人走的是会员系统
                param.put("firstExector", firstExecutor + "");
                param.put("secondExector", secondExecutor + "");

                Integer applyId = transactionService.createApplyWithout(businessNameEn, "transport_purchase_out", objDTO.getId(), objDTO.getAdminId(), param);
                if (applyId > 0) {
                    out_apply = applyId;

                    //更新出库表中的applyId
                    TransportPurchaseOutDTO updateDto = new TransportPurchaseOutDTO();
                    updateDto.setId(objDTO.getId());
                    updateDto.setApplyId(applyId);
                    purchaseOutService.updateInfoById(updateDto);

                } else {
                    //审批流程生成失败 删除已经生成的出库单
                    purchaseOutService.delete(objDTO.getId());

                    //程序终止，返回失败信息
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //endregion

            } else {
                //更新
                //将不需要更新的字段设置为NULL
                Boolean isNext = purchaseOutService.updateInfoById(objDTO);

                if (!isNext) {
                    //操作失败
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
            }

            //region 出库明细表.保存成功后更新出库明细表
            String[] f_id = request.getParameterValues("f_id");
            String[] f_partid = request.getParameterValues("f_partid");
            String[] f_cstore_count = request.getParameterValues("f_cstore_count");
            String[] f_ccount = request.getParameterValues("f_ccount");

            //1.获取已保存的出库明细
            TransportPurchaseDetailDTOQuery detailQuery = new TransportPurchaseDetailDTOQuery();
            detailQuery.setTableId(205);
            detailQuery.setPurId(objDTO.getId());
            detailQuery.setStopFlag(0);
            detailQuery.setPageSize(100);
            Page<TransportPurchaseDetailDTO> oldPlanPage = purchaseDetailService.getForPage(detailQuery);

            //2. 保存到数据库
            if (f_id != null && f_id.length > 0) {

                List<Integer> newPlanIds = new ArrayList<>(); //提交上来的，已保存过的ID
                TransportPurchaseDetailDTO insert;
                Date default_date = DateConvertUtils.strToDate("1990-01-01");

                for (int i = 0; i < f_id.length; i++) {
                    if (Integer.parseInt(f_ccount[i]) <= 0) {
                        continue;
                    }

                    insert = new TransportPurchaseDetailDTO();
                    insert.setParentId(0);
                    insert.setTableId(205);
                    insert.setRecordId(objDTO.getId());
                    insert.setPurchaseType(objDTO.getPurchaseType());
                    insert.setPartId(Integer.parseInt(f_partid[i]));
                    insert.setProId(0);
                    insert.setPurId(objDTO.getId());
                    insert.setOpType(objDTO.getOutType() == 4 ? 3 : 2); //outtype=4是报废，其它是出库
                    insert.setrPurchaseType(0);
                    insert.setrPurchaser(0);
                    insert.setrCompanyId(0);
                    insert.setrPayCompanyId(0);
                    insert.setrPayWay(0);
                    insert.setrPrice(BigDecimal.ZERO);
                    insert.setrCount(0);
                    insert.setrInCount(0);
                    insert.setrAmount(BigDecimal.ZERO);
                    insert.setrTaxRate(BigDecimal.ZERO);
                    insert.setrTax(BigDecimal.ZERO);
                    insert.setrStoreCount(0);
                    insert.setrPurchaseDate(default_date);
                    insert.setrInDate(default_date);
                    insert.setrSalePrice(BigDecimal.ZERO);
                    insert.setrMarketPrice(BigDecimal.ZERO);
                    insert.setrStorePrice(BigDecimal.ZERO);

                    //以下根据出库方式决定是“出库”还是“报废”
                    if (objDTO.getOutType() == 4) {
                        //报废
                        insert.setcOutType(objDTO.getOutType());
                        insert.setcNoOrder(0);
                        insert.setcCount(0);
                        insert.setcCountAll(0);
                        insert.setcCountReal(0);
                        insert.setcCountReturn(0);
                        insert.setcCountNouse(0);
                        insert.setcRepairId(0);
                        insert.setcCarId(0);
                        insert.setcDriverId(0);
                        insert.setcUserId(0);
                        insert.setcOutDate(default_date);

                        insert.setsCount(Integer.parseInt(f_ccount[i]));
                        insert.setsAdminId(objDTO.getReceiver());
                        insert.setsDate(objDTO.getReceiveDate());
                        insert.setsReason(objDTO.getRemark());
                    } else {
                        //出库
                        insert.setcOutType(objDTO.getOutType());
                        insert.setcNoOrder(0);
                        insert.setcStoreCount(Integer.parseInt(f_cstore_count[i]));
                        insert.setcCount(Integer.parseInt(f_ccount[i]));
                        insert.setcCountAll(insert.getcCount());
                        insert.setcCountReal(insert.getcCount());
                        insert.setcCountReturn(0);
                        insert.setcCountNouse(0);
                        insert.setcRepairId(0);
                        insert.setcCarId(objDTO.getCarId());
                        insert.setcDriverId(objDTO.getDriverId());
                        insert.setcUserId(objDTO.getReceiver());
                        insert.setcOutDate(objDTO.getReceiveDate());

                        insert.setsCount(0);
                        insert.setsAdminId(0);
                        insert.setsDate(default_date);
                    }

                    insert.setReviewer(0);
                    insert.setReviewDate(default_date);
                    insert.setReviewStatus(0);
                    insert.setStatus(0);
                    insert.setBxId(0);
                    insert.setApplyId(out_apply);
                    insert.setRelationId(objDTO.getRelationId());
                    insert.setAdminId(curr_obj.getId());
                    insert.setCreateTime(new Date());
                    insert.setStopFlag(0);
                    insert.setDeleteFlag(0);

                    //更新或插入
                    int id = Integer.parseInt(f_id[i]);
                    if (id > 0) {
                        //更新
                        newPlanIds.add(id);
                        insert.setId(id);
                        purchaseDetailService.updateInfoById(insert);
                    } else {
                        //插入
                        purchaseDetailService.insert(insert);
                    }
                }

                //3.不存在新列表中的则表示已经删除了
                for (TransportPurchaseDetailDTO item : oldPlanPage.getItems()) {
                    if (!newPlanIds.contains(item.getId())) {
                        purchaseDetailService.delete(item.getId());
                    }
                }
            }
            //endregion

            //操作成功 结果返回
            map = OperateCode.CompositionResult(map, 1);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            if (outid > 0) {
                //删除已经生成的出库单
                purchaseOutService.delete(outid);

                //删除已出库的记录
                TransportPurchaseDetailDTOQuery detailQuery = new TransportPurchaseDetailDTOQuery();
                detailQuery.setW_tableId(205);
                detailQuery.setW_purId(outid);
                detailQuery.setDeleteFlag(1);
                purchaseDetailService.updateInfoByQuery(detailQuery);

                //删除审批单
                applyManageService.delete(out_apply);
            }

            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }
    //endregion

    //region 删除&改变状态

    /**
     * 通过id删除 ajax异步
     *
     * @param id 记录id
     * @return json
     */
    @RequestMapping(value = "/deleteById", method = RequestMethod.POST)
    @ResponseBody
    public String deleteNotify(Integer id) {

        // 结果返回结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        if (id == null || id <= 0) {
            map = OperateCode.CompositionResult(map, -10, "请选择要删除的记录！");
            result = JSONUtils.toJSON(map);
            return result;
        }

        try {
            Boolean isNext = purchaseOutService.delete(id);
            map = OperateCode.CompositionResult(map, isNext ? 1 : 0);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }

    /**
     * 状态改变 ajax异步
     *
     * @param id     记录id
     * @param status 状态
     * @return json
     */
    @RequestMapping(value = "/changeFlag", method = RequestMethod.POST)
    @ResponseBody
    public String openOrStopFlag(Integer id, Integer status) {

        // 结果返回 结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        try {
            Boolean isNext = purchaseOutService.changeState(id, status);
            map = OperateCode.CompositionResult(map, isNext ? 1 : 0);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }
    //endregion

    //region 数据查看

    /**
     * 数据查看
     *
     * @param model     model模型
     * @param id        主键id
     * @param tableName 数据库英文表名
     * @return model
     */
    @RequestMapping(value = "/show", method = RequestMethod.POST)
    public String show(Model model, Integer id, String tableName) {
        id = (id == null ? 0 : id);

        TransportPurchaseOutDTO obj = new TransportPurchaseOutDTO();
        obj.setId(id);

        if (id > 0) {
            obj = purchaseOutService.getById(id);
        }
        purchaseOutService.assembleObjInfo(model, tableName, obj);

        return "show/show-template";
    }

    //endregion

}